package gaml.java.serializer.collection;

import gaml.error.GamlException;
import gaml.java.ClassSerializer;
import gaml.java.ClassSerializerStore;
import gaml.java.NodeObjectBridge;
import gaml.yaml.MappingNode;
import gaml.yaml.YamlNode;
import gaml.yaml.ahchor.YamlAnchorCodeStore;
import gaml.yaml.ahchor.YamlAnchorObjectStore;

import java.util.Map;
import java.util.Set;


public abstract class MapSerializer <T extends Map <Object, Object>> implements ClassSerializer <T> {
	final static String incorrectNodeTypeError = "Node [%s] should be a mapping node";
	static final String incorrectObjectError = "Object [%s] should implement Map";
	
	ClassSerializerStore store = null;
	
	public MapSerializer (ClassSerializerStore store) { this.store = store; }
	
	@Override
	public YamlNode serialize (YamlNode node, T object, YamlAnchorObjectStore anchors) throws GamlException {
		if (! (node instanceof MappingNode)) throw new GamlException (String.format (incorrectNodeTypeError, node.toString ()));
	
		node.setTag (object.getClass ().getName ());
		for (Object key: object.keySet ())
			node.addChild (
					NodeObjectBridge.create (key, node, (Class <Object>) key.getClass (), store).parseObject (anchors).getNode ().setTag (key.getClass ().getName ()), 
					NodeObjectBridge.create (object.get (key), node, (Class <Object>) object.get (key).getClass (), store).parseObject (anchors).getNode ().setTag (object.get (key).getClass ().getName ()));

	
		return node;
	}

	@Override
	public YamlNode createNode (YamlNode parent) { return new MappingNode (parent);	}

	@Override
	public T restore (YamlNode node, T object, YamlAnchorCodeStore anchors) throws GamlException {
		if (! (object instanceof Map)) throw new GamlException (String.format (incorrectObjectError, object));
		
		for (YamlNode key: node.getMappingChildren ().keySet ()) {
 			try { object.put (
 					NodeObjectBridge.create (key, Class.forName (key.getTag ()), store).parseNode (anchors).getObject (), 
 					NodeObjectBridge.create (node.getChild (key), Class.forName (node.getChild (key).getTag ()), store).parseNode (anchors).getObject ()); }
 			catch (ClassNotFoundException e) { throw new GamlException (e); }
		}
		
		return object;
	}
	
	@Override
	public boolean noAnchor () { return false; }
}